package servlets;

import basicas.Assunto;
import basicas.Usuario;
import fachadas.FachadaDePerguntas;
import fachadas.FachadaDeUsuarios;
import fachadas.FachadaEstatisticas;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import pergunta.EstatisticaPergunta;
import pergunta.Pergunta;

/**
 *
 * @author Diego
 */
public class ServletDeEstatisticas extends HttpServlet {

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession sessao = request.getSession();
        List listaDeUsuariosNoRanking;//essa lista vai pegar todos os usuarios em ordem na tabela ranking
        List posicoesDosUsuariosNoRanking;//essa lista vai guardar apenas as pontuacoes dos usuarios na msma tabela
        List<Integer> estatisticasDoUsuario;//aqui sao as estatisticas do usuario q esta logado no momento.
        List<Usuario> listaFinalDeUsuarios = null;
        int acertos = 0, erros = 0, total = 0;
        Usuario user = (Usuario) sessao.getAttribute("usuario");
        FachadaDePerguntas f = FachadaDePerguntas.getInstance();
        FachadaEstatisticas fe = FachadaEstatisticas.getInstance();

        estatisticasDoUsuario = f.listarEstatisticas(user.getId());
        posicoesDosUsuariosNoRanking = f.listarPosicoesDoRanking();
        listaDeUsuariosNoRanking = f.listarUsuariosDoRanking();

        List<Pergunta> dadosDetalhadosUsuario = f.obterEstatisticasDetalhadas(user.getId());

        LinkedHashMap dadosDificuldade = calcularEstatisticasDificuldade(dadosDetalhadosUsuario);
        String strDificuldade = geraStringGraficoDificuldade(dadosDificuldade);
        HashMap dadosAcertosAssunto = calcularEstatisticasAcertoAssunto(dadosDetalhadosUsuario);
        String[] strAcertosAssunto = geraStringGraficoAcertoAssunto(dadosAcertosAssunto);

        LinkedHashMap dadosAcertoDificuldade = calcularEstatisticasAcertoDific(dadosDetalhadosUsuario);
        String[] strAcertosDific = geraStringGraficoAcertoDific(dadosAcertoDificuldade);
        
        EstatisticaPergunta estatisticaperguntaMaiorTaxaDeErro = fe.pegaPerguntaMaiorTaxaErro();
        Pergunta perguntaMaiorTaxaErro = f.obterPerguntaPorId(estatisticaperguntaMaiorTaxaDeErro.getIdPergunta());

        request.setAttribute("dadosDificuldade", strDificuldade);
        request.setAttribute("dadosAcertoAssunto", strAcertosAssunto);
        request.setAttribute("dadosAcertoDificuldade", strAcertosDific);
        
        request.setAttribute("perguntaMaiorTaxaErro", perguntaMaiorTaxaErro);
        request.setAttribute("acertosErrosPerguntaMaiorTaxaErro", estatisticaperguntaMaiorTaxaDeErro);
        try {
            listaFinalDeUsuarios = gerarListaDeUsuarios(listaDeUsuariosNoRanking);
        } catch (NullPointerException ex) {
            listaFinalDeUsuarios = null;
        } catch (SQLException ex) {
            Logger.getLogger(ServletDeEstatisticas.class.getName()).log(Level.SEVERE, null, ex);
        }
        acertos = estatisticasDoUsuario.get(0);//NÃO MEXAM NESSA ORDEM!!!
        //isso é um padrao.
        erros = estatisticasDoUsuario.get(1);

        total = estatisticasDoUsuario.get(2);




        request.setAttribute("acertos", acertos);
        request.setAttribute("erros", erros);
        request.setAttribute("total", total);
        request.setAttribute("usuarios", listaFinalDeUsuarios);
        request.setAttribute("posicoes", posicoesDosUsuariosNoRanking);
        request.getRequestDispatcher("User/estatisticas.jsp").forward(request, response);
    }

    //essa função vai pegar todos os id's que recebeu da tabela ranking pragt poder imprimir o nome dos usuarios na pág
    private List<Usuario> gerarListaDeUsuarios(List<Integer> listaRecebida) throws NullPointerException, SQLException {
        List<Usuario> retorno = new ArrayList<Usuario>();
        Usuario u = null;
        int i = 0;
        int id;
        FachadaDeUsuarios f = new FachadaDeUsuarios();

        do {
            id = listaRecebida.get(i);

            u = f.getUsuarioPorId(id);

            retorno.add(u);
            ++i;
        } while (i < listaRecebida.size());


        return retorno;
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

    private LinkedHashMap calcularEstatisticasDificuldade(List<Pergunta> dados) {
        LinkedHashMap resultado = new LinkedHashMap(3);
        for (int i = 0; i < 3; i++) {
            int[] dadosDificuldade = calcularAcertosErrosDificuldade(dados, i);
            String chave = "";
            switch (i) {
                case 0:
                    chave = "Fácil";
                    break;
                case 1:
                    chave = "Médio";
                    break;
                case 2:
                    chave = "Difícil";
                    break;
            }

            resultado.put(chave, dadosDificuldade);
        }
        return resultado;
    }

    private int[] calcularAcertosErrosDificuldade(List<Pergunta> dados, int i) {
        int acertos = 0;
        int erros = 0;
        for (Pergunta p : dados) {
            if (p.getDificuldade() == i) {
                if (p.getAcertou()) {
                    acertos++;
                } else {
                    erros++;
                }
            }
        }
        int[] acertosErros = new int[2];
        acertosErros[0] = acertos;
        acertosErros[1] = erros;
        return acertosErros;
    }

    private HashMap calcularEstatisticasAcertoAssunto(List<Pergunta> dados) {
        FachadaDePerguntas f = new FachadaDePerguntas();
        try {
            List<Assunto> assuntos = f.listarTemas();
            HashMap estat = new HashMap(assuntos.size());
            for (Assunto tema : assuntos) {
                int[] acertosErros = {0, 0};
                for (Pergunta p : dados) {
                    if (p.getId_tema() == tema.getId()) {
                        if (p.getAcertou()) {
                            acertosErros[0]++;
                        } else {
                            acertosErros[1]++;
                        }
                    }
                }
                estat.put(tema.getNome(), acertosErros);
            }
            return estat;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    private LinkedHashMap calcularEstatisticasAcertoDific(List<Pergunta> dados) {
        FachadaDePerguntas f = new FachadaDePerguntas();
        try {
            List<Assunto> assuntos = f.listarTemas();
            LinkedHashMap estat = new LinkedHashMap(assuntos.size());

            for (int dif = 0; dif < 3; dif++) {
                String dificuldade = "";
                int[] acertosErros = {0, 0};
                for (Pergunta p : dados) {
                    if (p.getDificuldade() == dif) {
                        if (p.getAcertou()) {
                            acertosErros[0]++;
                        } else {
                            acertosErros[1]++;
                        }
                    }
                }
                switch (dif) {
                    case 0:
                        dificuldade = "Fácil";
                        break;
                    case 1:
                        dificuldade = "Médio";
                        break;
                    case 2:
                        dificuldade = "Difícil";
                        break;
                }
                estat.put(dificuldade, acertosErros);
            }
            return estat;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String[] geraStringGraficoAcertoDific(HashMap<String, int[]> dados) {
        String xaxis = "[";
        int[] acertos = new int[dados.entrySet().size()];
        int[] erros = new int[dados.entrySet().size()];

        int count = 0;
        for (Entry<String, int[]> dif : dados.entrySet()) {
            xaxis += "'" + dif.getKey() + "'";
            if (count < (dados.entrySet().size() - 1)) {
                xaxis += ", ";
            }
            acertos[count] = dif.getValue()[0];
            erros[count] = dif.getValue()[1];

            count++;

        }
        xaxis += "]";
        count = 0;
        String series = "[{name: 'Erros', data: [";
        for (int qtde : erros) {
            series += erros[count];
            if (count < erros.length - 1) {
                series += ", ";
            }
            count++;
        }
        count = 0;
        series += "]}, ";
        series += "{name: 'Acertos', data: [";
        for (int qtde : acertos) {
            series += acertos[count];
            if (count < acertos.length - 1) {
                series += ", ";
            }
            count++;
        }
        series += "]}] ";
        String[] strResult = {xaxis, series};
        return strResult;
    }

    private String geraStringGraficoDificuldade(LinkedHashMap<String, int[]> dadosDificuldade) {
        String strDificuldades = "";
        int count = 0;
        for (Entry<String, int[]> dif : dadosDificuldade.entrySet()) {
            strDificuldades += "['" + dif.getKey() + "', ";
            int total = 0;
            total += dif.getValue()[0] + dif.getValue()[1];
            strDificuldades += total + "]";
            if (count < dadosDificuldade.entrySet().size()) {
                strDificuldades += ", ";
            }
        }
        return strDificuldades;
    }

    private String[] geraStringGraficoAcertoAssunto(HashMap<String, int[]> dadosAcertosAssunto) {
        String xaxis = "[";
        int[] acertos = new int[dadosAcertosAssunto.entrySet().size()];
        int[] erros = new int[dadosAcertosAssunto.entrySet().size()];

        int count = 0;
        for (Entry<String, int[]> dif : dadosAcertosAssunto.entrySet()) {
            xaxis += "'" + dif.getKey() + "'";
            if (count < (dadosAcertosAssunto.entrySet().size() - 1)) {
                xaxis += ", ";
            }
            acertos[count] = dif.getValue()[0];
            erros[count] = dif.getValue()[1];

            count++;

        }
        xaxis += "]";
        count = 0;
        String series = "[{name: 'Erros', data: [";
        for (int qtde : erros) {
            series += erros[count];
            if (count < erros.length - 1) {
                series += ", ";
            }
            count++;
        }
        count = 0;
        series += "]}, ";
        series += "{name: 'Acertos', data: [";
        for (int qtde : acertos) {
            series += acertos[count];
            if (count < acertos.length - 1) {
                series += ", ";
            }
            count++;
        }
        series += "]}] ";
        String[] strResult = {xaxis, series};
        return strResult;
    }
}
